/*
 * DateTime.java
 *
 * $Id: DateTime.java,v 1.1 2008-03-18 12:58:46 mario Exp $
 */
package org.ceteca.explica.core.util;

import java.text.SimpleDateFormat;

import java.util.Calendar;
import java.util.GregorianCalendar;

import org.ceteca.explica.core.InterfaceExplica;

/**
 * Utils for conversion between Dates and Strings.
 * <br/>
 * @author Mario García García <mario@imagos.es>
 * Copyright (c) 2007 Fundación Centro Tecnolóxico da Carne
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * <br/>
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * <br/>
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
public class DateTime {
    /**
     * Date formatted for SQL use.
     */
    private java.sql.Date sqlDate;
    /**
     * Date formatted for normal use.
     */
    private java.util.Date utDate;
    /**
     * Date parser and formatter.
     */
    private SimpleDateFormat df;
    
    /**
     * Default constructor
     */
    public DateTime() {
        sqlDate = null;
        utDate = null;
        df = null;
    }
    
    /**
     * Copy constructor.
     */
    public DateTime(DateTime d) {
        super();
        this.df = d.df;
        this.utDate = d.utDate;
        this.sqlDate = d.sqlDate;
    }
    
    /**
     * Constructor from a date in String format.
     * @param date String, date in String format.
     * @param format String, date pattern for formatting the string.
     */
    public DateTime(String date, String format) {
        this.setDateFormat(format);
        this.setDate(date);
    }
    
    /**
     * Constructor from a date in normal format (util.Date format)
     * @param date java.util.Date, date in util.Date format.
     * @param format String, date pattern for formatting the string.
     */
    public DateTime(java.util.Date date, String format) {
        this.setDateFormat(format);
        this.setDate(date);
    }
    
    /**
     * Constructor from a date in SQL format (sql.Date format)
     * @param date java.sql.Date, date in sql.Date format.
     * @param format String, date pattern for formatting the string.
     */
    public DateTime(java.sql.Date date, String format) {
        this.setDateFormat(format);
        this.setDate(date);
    }
    
    /**
     * Set the pattern for formatting dates that will be used.
     * @param format String, date format pattern.
     */
    public void setDateFormat(String format) {
        if (format != null)
            df = new SimpleDateFormat(format);
        else
            df = null;
    }
    
    /**
     * Set the dateTime value
     * @param date java.util.Date, date in util.Date format.
     */
    public void setDate(java.util.Date date) {
        if (date != null) {
            this.utDate = date;
            this.sqlDate = new java.sql.Date(date.getTime());
        }
    }
    
    /**
     * Set the dateTime value
     * @param date java.util.Date, date in sql.Date format.
     */
    public void setDate(java.sql.Date date) {
        if (date != null) {
        	this.utDate = new java.util.Date(date.getTime());
            this.sqlDate = date;
        }
    }
    
    /**
     * Set the dateTime value
     * @param date String, date in String format.
     */
    public void setDate(String date) {
        if (date != null && date.length() > 0 && this.df != null) {
            try {
                this.utDate = this.df.parse(date);
                this.sqlDate = new java.sql.Date(this.utDate.getTime());
            }
            catch (Exception ex) {
                this.utDate = null;
                this.sqlDate = null;
            }
        }
    }
    
    /**
     * Get the datetime value formatted as String.
     * @return String, String value of the datetime.
     */
    public String getDateAsString() {
        String result = "";
        if (this.utDate != null && this.df != null) {
            try {
                result = this.df.format(this.utDate);
            }
            catch (Exception ex) {
                result = "";
            }
        }
        else
            result = "";
        
        return result;
    }
    
    /**
     * Get the datetime value formatted as SQL compatible date.
     * @return java.sql.Date, datetime value in SQL format.
     */
    public java.sql.Date getDate() {
        return this.sqlDate;
    }
    
    /**
     * Add days to the datetime value
     * @param days int, number of days to add.
     */
    public void addDays(int days) {
        if (this.utDate != null) {
            Calendar cal = new GregorianCalendar();
            cal.setTimeInMillis(utDate.getTime());
            cal.add(Calendar.DATE, days);
            this.setDate(cal.getTime());
        }
    }
    
    /**
     * Add months to the datetime value
     * @param months int, number of months to add.
     */
    public void addMonths(int months) {
        if (this.utDate != null) {
            Calendar cal = new GregorianCalendar();
            cal.setTimeInMillis(utDate.getTime());
            cal.add(Calendar.MONTH, months);
            this.setDate(cal.getTime());
        }
    }
    
    /**
     * Add years to the datetime value.
     * @param years int, number of years to add.
     */
    public void addYears(int years) {
        if (this.utDate != null) {
            Calendar cal = new GregorianCalendar();
            cal.setTimeInMillis(utDate.getTime());
            cal.add(Calendar.YEAR, years);
            this.setDate(cal.getTime());
        }
    }
    
    /**
     * Get the day of the datetime value.
     * @return String, day of the datetime value.
     */
    public String getDay() {
        if (this.utDate != null) {
            Calendar cal = new GregorianCalendar();
            cal.setTimeInMillis(utDate.getTime());
            return "" + cal.get(Calendar.DAY_OF_MONTH);
        }
        else
            return null;
    }
    
    /**
     * Get the day of the datetime value as an integer.
     * @return int, day of the datetime value.
     */
    public int getDayAsInt() {
        if (this.utDate != null) {
            Calendar cal = new GregorianCalendar();
            cal.setTimeInMillis(utDate.getTime());
            return cal.get(Calendar.DAY_OF_MONTH);
        }
        else
            return -1;
    }

    
    /**
     * Get the weekday of the datetime value.
     * @return String, weekday of the datetime value.
     */
    public String getWeekDay() {
        if (this.utDate != null) {
            Calendar cal = new GregorianCalendar();
            cal.setTimeInMillis(utDate.getTime());
            return "" + cal.get(Calendar.DAY_OF_WEEK);
        }
        else
            return null;
    }
    
    
    /**
     * Get the month of the datetime value.
     * @return String, month of the datetime value.
     */
    public String getMonth() {
        if (this.utDate != null) {
            Calendar cal = new GregorianCalendar();
            cal.setTimeInMillis(utDate.getTime());
            return "" + cal.get(Calendar.MONTH);
        }
        else
            return null;
    }
    
    /**
     * Get the month of the datetime value as an integer.
     * @return int, month of the datetime value.
     */
    public int getMonthAsInt() {
        if (this.utDate != null) {
            Calendar cal = new GregorianCalendar();
            cal.setTimeInMillis(utDate.getTime());
            return cal.get(Calendar.MONTH);
        }
        else
            return -1;
    }
    
    /**
     * Get the year of the datetime value.
     * @return String, year of the datetime value.
     */
    public String getYear() {
        if (this.utDate != null) {
            Calendar cal = new GregorianCalendar();
            cal.setTimeInMillis(utDate.getTime());
            return "" + cal.get(Calendar.YEAR);
        }
        else
            return null;
    }
    
    /**
     * Get the year of the datetime value as an integer.
     * @return int, year of the datetime value.
     */
    public int getYearAsInt() {
        if (this.utDate != null) {
            Calendar cal = new GregorianCalendar();
            cal.setTimeInMillis(utDate.getTime());
            return cal.get(Calendar.YEAR);
        }
        else
            return -1;
    }
    
    /**
     * Get the age, in years passed from the datetime value to the current day.
     * @return int, age.
     */
    public int getAge() {
        int result = -1;
        if (this.utDate != null) {
            try {
                DateTime today = new DateTime(new java.util.Date(System.currentTimeMillis()), 
                    InterfaceExplica.CONST_SHORT_DATE_PATTERN);
                result = today.getYearAsInt() - this.getYearAsInt();
                
                if (this.getMonthAsInt() > today.getMonthAsInt())
                    result --;
                else if (this.getMonthAsInt() == today.getMonthAsInt() &&
                        this.getDayAsInt() > today.getDayAsInt())
                    result --;
            }
            catch (Exception ex) {
                result = -1;
            } // catch
        }
        
        return result;
    }
    
    /**
     * Devuelve el tag Id de CVS asociado al fuente del fichero.
     */
    public static String getRevision() {
        return "$Id: DateTime.java,v 1.1 2008-03-18 12:58:46 mario Exp $";
    }
}
